package com.yixun.qfbao.util;

import com.yixun.qfbao.api.service.ThirdPartyApiService;
import com.yixun.qfbao.model.Company;
import com.yixun.qfbao.model.CompanyWxconfig;
import com.yixun.qfbao.model.dto.CompanyWxconfigDto;
import com.yixun.qfbao.model.enums.DelFlagEnum;
import com.yixun.qfbao.model.enums.SystemIdEnum;
import com.yixun.qfbao.model.enums.WxConfigEnum;
import com.yixun.qfbao.service.CompanyWxconfigService;
import com.yixun.qfbao.service.SubscriptionService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class WxAccessTokenCacheUtils {
    private static final Logger logger = LoggerFactory.getLogger(WxAccessTokenCacheUtils.class);

    @Autowired
    private CompanyWxconfigService companyWxconfigService;
    @Autowired
    private ThirdPartyApiService thirdPartyApiService;
    @Autowired
    private SubscriptionService subscriptionService;
    @Autowired
	private WeixinCommon weixinCommon;

    public synchronized void put(String key, String systemId, String accessToken) {
        try {
        	String appId = weixinCommon.getRealAppId(systemId, key);
        	if(StringUtils.isEmpty(appId)) {
        		return;
        	}
//            key = key+"_accessToken_"+systemId;
            RedisUtil.setEx(appId, accessToken, 5000L, TimeUnit.SECONDS);
        } catch (Exception e) {
            logger.info("缓存微信accesstoken失败:", e);
        }
    }

    public synchronized String get(String key,String systemId) {
        try {
//            key = key + "_accessToken_"+systemId;
            String appId = weixinCommon.getRealAppId(systemId, key);
        	if(StringUtils.isEmpty(appId)) {
        		return null;
        	}
            Object obj = RedisUtil.get(appId);
            if(obj == null) {
                return null;
            }
            return String.valueOf(obj);

        } catch (Exception e) {
            logger.error("查询缓存失败: {}", e);
        }
        return null;
    }

    public synchronized void remove(String key, String systemId) {
        try {
//            key = key+"_accessToken_"+systemId;
            String appId = weixinCommon.getRealAppId(systemId, key);
        	if(StringUtils.isEmpty(appId)) {
        		return;
        	}
            RedisUtil.delete(appId);
        } catch (Exception e) {
            logger.info("缓存微信accesstoken失败:", e);
        }
    }

    /**
     * @param companyUuid
     * @param systemId
     * @param domain
     * @return
     */
    public synchronized String getAccessToken(String companyUuid, String systemId, String domain) {
        String accessToken = null;
        CompanyWxconfigDto companyWxconfigDto = new CompanyWxconfigDto();
        companyWxconfigDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
        companyWxconfigDto.setCompanyUuid(companyUuid);
        companyWxconfigDto.setSystemId(systemId);
        companyWxconfigDto.setConfiged(WxConfigEnum.OPEN.getCode());
        CompanyWxconfig companyWxconfig = companyWxconfigService.selectBy(companyWxconfigDto);
        if (null == companyWxconfig) {
            logger.info("companyWxconfig is null !!!");
            return null;
        }
        // todo 缓存刷掉造成的token失效问题，目前把最后一次获取的token更新到缓存中，以后若拆分再做考虑
        systemId = SystemIdEnum.ASSISTANT.getCode();
        accessToken = get(companyUuid, systemId);
        logger.info("accessToken redis value = " + accessToken);
        if(StringUtils.isNotBlank(accessToken)) {
            return accessToken;
        }
        logger.info("get token start .......");
        accessToken = thirdPartyApiService.getAccessTokenDefault(domain, companyUuid, systemId);
        logger.info("get token end .......,token value = " + accessToken);
        if(StringUtils.isNotBlank(accessToken)) {
            // todo 缓存刷掉造成的token失效问题，目前把最后一次获取的token更新到缓存中，以后若拆分再做考虑
            put(companyUuid, SystemIdEnum.AGENCY_h5.getCode(), accessToken);
            put(companyUuid, SystemIdEnum.ASSISTANT.getCode(), accessToken);
        }
        return accessToken;
    }
    
    /**
     * add by zilong.liu
     * 	以前的方法中使用的是固定的systemId 2，会导致不同渠道配置如果配置不一致的systemId时查询有误。慎用
     * 	本次更改只是简单的去掉了 systemId为渠道助手的赋值
     * @param companyUuid
     * @param systemId
     * @param domain
     * @return
     */
    public synchronized String getAccessTokenBySystemId(String companyUuid, String systemId, String domain) {
        String accessToken = null;
        CompanyWxconfigDto companyWxconfigDto = new CompanyWxconfigDto();
        companyWxconfigDto.setDelFlag(DelFlagEnum.UNDEL.getNo());
        companyWxconfigDto.setCompanyUuid(companyUuid);
        companyWxconfigDto.setSystemId(systemId);
        companyWxconfigDto.setConfiged(WxConfigEnum.OPEN.getCode());
        CompanyWxconfig companyWxconfig = companyWxconfigService.selectBy(companyWxconfigDto);
        if (null == companyWxconfig) {
            logger.info("companyWxconfig is null !!!");
            return null;
        }
        accessToken = get(companyUuid, systemId);
        logger.info("accessToken redis value = " + accessToken);
        if(StringUtils.isNotBlank(accessToken)) {
            return accessToken;
        }
    	logger.info("get token start .......");
    	accessToken = thirdPartyApiService.getAccessTokenDefault(domain, companyUuid, systemId);
        logger.info("get token end .......,token value = " + accessToken);
        if(StringUtils.isNotBlank(accessToken)) {
            put(companyUuid, systemId, accessToken);
        }
        
        return accessToken;
    }

    
    
    /**
     * add by zilong.liu
     * 	
     * @param company	总代公司company信息。传入必须为总代公司
     * @param lastSystemId 最后一次登录渠道
     * @return
     * 	此方法为消息发送改造升级时使用
     * 		由于不同的渠道要分发至不同的公众号，因此原token可能不对。
     * 		根据公司是否开启小程序消息配置以及人员是否有登录信息判断，是否需要重新获取accessToken。
     * 		需要注意做渠道的转换。
     * 		
     */
    public String getAccessTokenIfWeappMsg(Company company, String lastSystemId, String accessToken) {
    	if (company == null) {
    		return accessToken;
    	}
    	//1、判断公司是否开启小程序消息
    	String enableWeappMsg = company.getEnableWeappMsg();
    	if (!"1".equals(enableWeappMsg)) {
    		return accessToken;
    	}
    	if(StringUtils.isEmpty(lastSystemId) || "null".equals(lastSystemId)) {
    		return accessToken;
    	}
    	lastSystemId = convertWxSystemId(lastSystemId);
    	return getAccessTokenBySystemId(company.getCompanyUuid(), lastSystemId, "");
    }
    
    private static final Map<String, String> CONVERT_SYSTEM_INFO = new HashMap<>();
    
    @PostConstruct
    public void init() {
    	CONVERT_SYSTEM_INFO.put(SystemIdEnum.DEVELOPERS.getCode(), SystemIdEnum.ASSISTANT.getCode());
    	CONVERT_SYSTEM_INFO.put(SystemIdEnum.AGENCY_WEB.getCode(), SystemIdEnum.AGENCY_h5.getCode());
    	CONVERT_SYSTEM_INFO.put(SystemIdEnum.WEAPP_AGENCY.getCode(), SystemIdEnum.WEAPP_AGENCY_WX_ACCOUNTS.getCode());
    }
    
    
    /**
     * 	根据传入的systemId,获取微信公众号下发消息时对应的systemId
     * @param systemId
     * @return
     */
    public String convertWxSystemId(String systemId) {
    	if(StringUtils.isEmpty(systemId)) {
    		return systemId;
    	}
    	if(StringUtils.isEmpty(CONVERT_SYSTEM_INFO.get(systemId))) {
    		return systemId;
    	}
    	return CONVERT_SYSTEM_INFO.get(systemId);
    }
    
    /**
     * 小程序AccessToken
     * @return
     */
    public synchronized String getWeAppAgencyAccessToken() {
        String accessToken = null;
        String systemId = SystemIdEnum.WEAPP_AGENCY.getCode();
        accessToken = get("weeapp_agency", systemId);
        logger.info("weapp agency accessToken redis value = " + accessToken);
        if(StringUtils.isNotBlank(accessToken)) {
            return accessToken;
        }
        logger.info("get weapp agency token start .......");
        accessToken = thirdPartyApiService.getWeAppAccessTokenDefault(systemId);
        logger.info("get weapp agency token end .......,token value = " + accessToken);
        if(StringUtils.isNotBlank(accessToken)) {
            // todo 缓存刷掉造成的token失效问题，目前把最后一次获取的token更新到缓存中，以后若拆分再做考虑
            put("weeapp_agency", SystemIdEnum.WEAPP_AGENCY.getCode(), accessToken);
        }
        return accessToken;
    }

}
